
#include<iostream>
#include"func.h"
#include<opencv2/imgcodecs.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>
#include<opencv2/objdetect.hpp>
#include<opencv2/opencv.hpp>
#include<opencv2/ximgproc.hpp>
#include<string>
#include<vector>
#include<fstream>


using namespace std;
using namespace cv;

void drawapp(Mat result,Mat img2)//绘制轮廓函数
{
    int i;
    for(i=0;i<result.rows;i++)
    {
        if(i==result.rows-1)//最后一个点坐标与第一个点相连
        {
            Vec2i point1=result.at<Vec2i>(i);
            Vec2i point2=result.at<Vec2i>(0);
            line(img2,point1,point2,Scalar(0,0,255),2,8,0);
            break;
        }
        Vec2i point1=result.at<Vec2i>(i);
        Vec2i point2=result.at<Vec2i>(i+1);
        line(img2,point1,point2,Scalar(0,0,255),2,8,0);
    }
}

void duobianxingbijin()
{
    Mat img,result;
    VideoCapture cap(0);
    Mat canny;

    Point2f center;

    Mat kernel=getStructuringElement(0,Size(3,3));

    vector<vector<Point>> contours;
    vector<Vec4i> hie;

    int t;

    RotatedRect rrect;

    while(1)
    {
        cap.read(img);

        Canny(img,canny,80,160,3,false);
        dilate(canny,canny,kernel);

        findContours(canny,contours,hie,0,2,Point());

        for(t=0;t<contours.size();t++)
        {
            rrect=minAreaRect(contours[t]);
            center=rrect.center;
            circle(img,center,2,Scalar(0,255,0),2,8,0);

            approxPolyDP(contours[t],result,4,true);//多边形逼近函数(轮廓像素点，逼近结果顶点坐标，逼近精度，是否封闭标志)
            drawapp(result,img);

            if(result.rows==3)
            {
                putText(img,"triangle",center,0,1,Scalar(0,255,0),1,8);
            }
            if(result.rows==4)
            {
                putText(img,"retangle",center,0,1,Scalar(0,255,0),1,8);
            }
            if(result.rows==8)
            {
                putText(img,"poly-8",center,0,1,Scalar(0,255,0),1,8);
            }
            if(result.rows>12)
            {
                putText(img,"circle",center,0,1,Scalar(0,255,0),1,8);
            }

        }
        imshow("canny",canny);
        imshow("img",img);
        waitKey(1);

    }
}

void tubaojiance()
{

    VideoCapture cap(0);
    Mat img,imghsv;
    Mat mask;
    Mat st1 = getStructuringElement(MORPH_RECT,Size(11,11),Point(-1,-1));

    vector<vector<Point>> contours;
    vector<Vec4i> hie;
    vector<Point> hull;

    int n,i;

    while(1)
    {
        cap.read(img);

        //图像预处理
        cvtColor(img,imghsv,COLOR_BGR2HSV);
        Scalar upper(180,255,202);//多通道数据结构
        Scalar lower(62,0,81);
        inRange(imghsv,lower,upper,mask);
        morphologyEx(mask,mask,MORPH_OPEN,st1);//开运算去除较小区域

        //寻找轮廓
        findContours(mask,contours,hie,0,2,Point());
        for(n=0;n<contours.size();n++)
        {
            //计算凸包
            convexHull(contours[n],hull);//计算凸包函数(输入二维点集或轮廓坐标，输出凸包顶点)
            //绘制凸包
            for(i=0;i<hull.size();i++)
            {
                //绘制凸包顶点
                circle(img,hull[i],4,Scalar(255,0,0),2,8,0);
                //连接凸包
                if(i==hull.size()-1)//最后一个点
                {
                    line(img,hull[i],hull[0],Scalar(0,0,255),2,8,0);
                    break;
                }
                line(img,hull[i],hull[i+1],Scalar(0,0,255),2,8,0);
            }
        }

        imshow("mask",mask);
        imshow("img",img);
        waitKey(1);
    }

}

void drawline(Mat &img,
                vector<Vec2f> lines,
                double rows,
                double cols,
                Scalar scalar,
                int n)
{
    Point pt1,pt2;
    for(size_t i=0;i<lines.size();i++)
    {
        float rho=lines[i][0];
        float theta=lines[i][1];
        double a=cos(theta);
        double b=sin(theta);
        double x0=a*rho,y0=b*rho;
        double length=max(rows,cols);

        pt1.x=cvRound(x0+length*(-b));
        pt1.y=cvRound(y0+length*(a));

        pt2.x=cvRound(x0-length*(-b));
        pt2.x=cvRound(y0-length*(a));

        line(img,pt1,pt2,scalar,n);

    }
}

void zhixianjiance()
{
    VideoCapture cap(0);

    Mat img,edge,img1,img2;

    vector<Vec2f> lines1,lines2;

    while(1)
    {
        cap.read(img);
        cvtColor(img,img,COLOR_BGR2GRAY);
        Canny(img,edge,80,180,3,false);
        threshold(edge,edge,170,255,THRESH_BINARY);

        HoughLines(edge,lines1,1,CV_PI/180,50,0,0);//霍夫变换直线检测函数(原图，输出量，单位距离分辨率，单位角度分辨率，距离分辨率除数，单位角度分辨率除数)
        HoughLines(edge,lines2,1,CV_PI/180,150,0,0);
         
        img.copyTo(img1);
        img.copyTo(img2);
        drawline(img1,lines1,edge.rows,edge.cols,Scalar(255),2);
        drawline(img2,lines2,edge.rows,edge.cols,Scalar(255),2);

        imshow("edge",edge);
        imshow("img",img);
        imshow("img1",img1);
        imshow("img2",img2);
        
        waitKey(1);

    }

}

void zhixianjianceP()
{
    VideoCapture cap(0);

    Mat img,edge,img1,img2;

    vector<Vec4i> lines1,lines2;

    while(1)
    {
        cap.read(img);
        cvtColor(img,img,COLOR_BGR2GRAY);
        Canny(img,edge,80,180,3,false);
        threshold(edge,edge,170,255,THRESH_BINARY);

        HoughLinesP(edge,lines1,1,CV_PI/180,50,30,10);//霍夫变换直线检测函数(原图，直线端点坐标，单位距离分辨率，单位角度分辨率，最小长度，最大长度)
        HoughLinesP(edge,lines2,1,CV_PI/180,150,30,30);
         
        img.copyTo(img1);
        img.copyTo(img2);
        for(size_t i=0;i<lines1.size();i++)
        {
            line(img1,Point(lines1[i][0],lines1[i][1]),Point(lines1[i][2],lines1[i][3]),Scalar(255),3);
        }
        for(size_t i=0;i<lines1.size();i++)
        {
            line(img2,Point(lines2[i][0],lines2[i][1]),Point(lines2[i][2],lines2[i][3]),Scalar(255),3);
        }

        imshow("edge",edge);
        imshow("img",img);
        imshow("img1",img1);
        imshow("img2",img2);
        
        waitKey(1);

    }

}

void dianjinihe()
{
    Vec4f lines;
    vector<Point2f> point;
    const static float Points[20][2] = 
    {
		{ 0.0f,   0.0f },{ 10.0f,  11.0f },{ 21.0f,  20.0f },{ 30.0f,  30.0f },
		{ 40.0f,  42.0f },{ 50.0f,  50.0f },{ 60.0f,  60.0f },{ 70.0f,  70.0f },
		{ 80.0f,  80.0f },{ 90.0f,  92.0f },{ 100.0f, 100.0f },{ 110.0f, 110.0f },
		{ 120.0f, 120.0f },{ 136.0f, 130.0f },{ 138.0f, 140.0f },{ 150.0f, 150.0f },
		{ 160.0f, 163.0f },{ 175.0f, 170.0f },{ 181.0f, 180.0f },{ 200.0f, 190.0f }
	};
    //将所有点存放在vector容器中
    for(int i=1;i<20;i++)
    {
        point.push_back(Point2f(Points[i][0],Points[i][1]));
    }
    double par=0;//距离类型的参数C
    double reps=0.01;//距离精度
    double aeps=0.01;//角度精度
    fitLine(point,lines,DIST_L1,0,0.01,0.01);//直线拟合函数(二三维点集，输出直线的参数，距离类型标志，距离类型参数，距离精度，角度精度)
    double k=lines[1]/lines[0];
    cout<<"k="<<k<<endl;
    cout<<"直线上一点坐标:("<<lines[2]<<","<<lines[3]<<")"<<endl;
    cout<<"解析式:y="<<k<<"(x-"<<lines[2]<<")+"<<lines[3]<<endl;
} 

void dianjinihe2()
{
    Mat img(500,500,CV_8UC3,Scalar::all(0));
    RNG& rng=theRNG();//生成随机点

    while(1)
    {
        int i,count=rng.uniform(1,101);
        vector<Point>points;

        //生成随机点
        for(i=0;i<count;i++)
        {
            Point pt;
            pt.x=rng.uniform(img.cols/4,img.rows*3/4);
            pt.y=rng.uniform(img.cols/4,img.rows*3/4);
            points.push_back(pt);
        }

        //拟合三角形
        vector<Point2f> triangle;
        double area=minEnclosingTriangle(points,triangle);//三角形拟合函数(二维点集，输出顶点坐标)

        //拟合圆形
        Point2f center;
        float radius=0;
        minEnclosingCircle(points,center,radius);//圆形拟合函数(二维点集，圆心坐标，半径)
        
        //创建图片输出结果
        img=Scalar::all(0);
        Mat img2;
        img.copyTo(img2);

        //绘制坐标点
        for(i=0;i<count;i++)
        {
            circle(img,points[i],3,Scalar(255,255,255),FILLED,LINE_AA);
            circle(img2,points[i],3,Scalar(255,255,255),FILLED,LINE_AA);
        }

        //绘制三角形
        for(i=0;i<3;i++)
        {
            if(i==2)
            {
                line(img,triangle[i],triangle[0],Scalar(255,255,255),1,16);
                break;
            }
            line(img,triangle[i],triangle[i+1],Scalar(255,255,255),1,16);
        }

        //绘制圆形
        circle(img2,center,cvRound(radius),Scalar(255,255,255),1,16);

        imshow("triangle",img);
        imshow("circle",img2);

        //退出程序
        char key=(char)waitKey();
        if (key==27||key=='q'||key=='Q');
        {
            break;
        }

    }
}

void qrcodereg()
{
    Mat img,gray;
    Mat qr;
    VideoCapture cap(2);
    QRCodeDetector qrcodedetector;//qr二维码检测函数在该类中
    vector<Point> points,points2;//二维码四个点坐标
    string information,information2;//二维码识别结果
    bool isQRcode;//是否检测到qr二维码

    while(1)
    {
        cap.read(img);
        cvtColor(img,gray,COLOR_BGR2GRAY);
        
        isQRcode=qrcodedetector.detect(gray,points);//二维码定位函数(输入图，四个顶点坐标)
        if(isQRcode)
        {
            //解码二维码
            information=qrcodedetector.decode(gray,points,qr);//二维码解码函数(输入图，二维码顶点，解码结果)
            cout<<points<<endl;
            // Mat qr8u=Mat_<char>(qr);
            // namedWindow("qrcode_bin",WINDOW_NORMAL);
            // imshow("qrcode_bin",qr8u);
        }
        else
        {

        }

        //绘制边框
        for(int i=0;i<points.size();i++)
        {
            if(i==points.size()-1)
            {
                line(img,points[i],points[0],Scalar(0,0,255),2,8);
                break;
            }
            line(img,points[i],points[i+1],Scalar(0,0,255),2,8);
        }
        //输出结果到图片
        putText(img,information.c_str(),Point(20,30),0,1.0,Scalar(0,0,255),2,8);

        //通过函数直接定位识别二维码
        information2=qrcodedetector.detectAndDecode(gray,points2);//二维码定位识别函数(输入图，顶点坐标)
        putText(img,information2.c_str(),Point(20,55),0,1.0,Scalar(0,0,255),2,8);

        
        imshow("img",img);

        waitKey(1); 

    }
}

void jifentuxiang()
{
    Mat img=Mat::ones(16,16,CV_32FC1);//创建图像

    //加入随机噪声
    RNG rng(10086);
    for(int x=0;x<img.rows;x++)
    {
        for(int y=0;y<img.cols;y++)
        {
            float d=rng.uniform(-0.5,0.5);
            img.at<float>(y,x)=img.at<float>(y,x)+d;
        }
    }

    //计算标准求和积分
    Mat sum;
    integral(img,sum);//求和积分函数(输入图，输出图)
    Mat sum8u=Mat_<char>(sum);//便于显示，转8U格式
    namedWindow("sum8u",WINDOW_NORMAL);
    imshow("sum8u",sum8u);

    //计算平方求和积分图像 
    Mat sqsum;
    integral(img,sum,sqsum);//求和积分函数(输入图，标准求和输出，平方求和输出)
    Mat sqsum8u=Mat_<char>(sqsum);
    namedWindow("sqsum8u",WINDOW_NORMAL);
    imshow("sqsum8u",sqsum8u);

    //计算倾斜积分图像
    Mat tilted;
    integral(img,sum,sqsum,tilted);//求和积分函数(输入图，标准求和输出，平方求和输出)
    Mat tilted8u=Mat_<char>(tilted);
    namedWindow("tilted8u",WINDOW_NORMAL);
    imshow("tilted8u",tilted8u);


    waitKey(0);

}

void manshuitianchongfenge()
{
    
    Mat img=imread("/home/zhanjiabin/桌面/task/study/test.jpg");
    RNG rng(10086);

    //设置操作标志flag
    int connectivity=4;
    int maskval=255;
    int flag=connectivity|(maskval<<8)|FLOODFILL_FIXED_RANGE;//漫水填充操作方法标志

    //设置与选中像素点差值
    Scalar lodiff=Scalar(20,20,20);
    Scalar updiff=Scalar(20,20,20);

    //声明掩码矩阵变量
    Mat mask=Mat::zeros(img.rows+2,img.cols+2,CV_8UC1);

    int py,px;
    Scalar newVal;
    Point point;

    int area;

    Rect r;

        
        while(1)
        {
            //随机产生像素点
            py=rng.uniform(0,img.rows-1);
            px=rng.uniform(0,img.cols-1);
            point=Point(px,py);

            //彩图中填充的像素值
            newVal=Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));

            area=floodFill(img,mask,point,newVal,&r,lodiff,updiff,flag);//漫水填充函数(输入输出图，掩码矩阵，种子点，新像素值，最小矩形边界，下界差值，上界差值，操作标志)

            //输出像素点和填充的像素数目
            cout<<"像素点:("<<point.x<<","<<point.y<<")"<<endl;
            cout<<"填充像素数目:"<<area<<endl;

            imshow("填充彩色图像",img);
            imshow("掩码图像",mask);

            int c=waitKey(0);
            if((c&255)==27)
            {
                break;
            }  
        }     

    
}

